<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>OpenLayers 各种类型的点标记</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v7.4.0/ol.css">
    <script src="https://cdn.jsdelivr.net/npm/ol@v7.4.0/dist/ol.js"></script>
    <style>
        html,
        body {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            overflow: hidden;
        }

        .map {
            width: 100%;
            height: 100%;
        }

        .coordinates {
            position: absolute;
            bottom: 10px;
            right: 10px;
            background: rgba(255, 255, 255, 0.8);
            padding: 5px 10px;
            border-radius: 4px;
            font-size: 12px;
            z-index: 1000;
        }

        /* 添加新增点按钮样式 */
        .add-point-btn {
            position: absolute;
            top: 10px;
            left: 10px;
            padding: 8px 15px;
            background: #409EFF;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            z-index: 1000;
            font-size: 14px;
        }

        .add-point-btn:hover {
            background: #66b1ff;
        }

        .add-point-btn.active {
            background: #67C23A;
        }

        .add-point-tip {
            position: absolute;
            top: 50px;
            left: 10px;
            padding: 8px 15px;
            background: rgba(255, 255, 255, 0.9);
            border-radius: 4px;
            z-index: 1000;
            font-size: 13px;
            display: none;
        }

        .add-point-tip.show {
            display: block;
        }

        /* 添加 GIF 标记样式 */
        .gif-marker {
            width: 32px;
            height: 32px;
            background-size: contain;
            background-repeat: no-repeat;
            background-position: center;
            pointer-events: none;
        }

        .marker-label {
            color: #333;
            background: rgba(255, 255, 255, 0.8);
            padding: 2px 5px;
            border-radius: 2px;
            font-size: 12px;
            white-space: nowrap;
            pointer-events: none;
        }
    </style>
</head>

<body>
    <div id="map" class="map"></div>

    <!-- 添加新增点按钮 -->
    <button id="addPointBtn" class="add-point-btn">新增点位</button>
    <div id="addPointTip" class="add-point-tip">点击地图添加新的点位</div>

    <!-- 坐标显示 -->
    <div id="coordinates" class="coordinates"></div>

    <script>
        /**
         * 点位数据数组
         * coordinates: 经纬度坐标 [经度, 纬度]
         * icon: 图标路径
         * pulse: 是否显示闪烁效果
         * pulseStartTime: 闪烁开始时间
         * size: 大小 [width, height]
         */
        const pointsData = [
            {
                type: 'scenic',
                name: '天安门',
                coordinates: [116.397428, 39.90923],
                icon: '/images/markers/PP_CJ.png',
                pulse: true,
                pulseStartTime: Date.now()
            },
            {
                type: 'hospital',
                name: '协和医院',
                coordinates: [116.417795, 39.913828],
                icon: '/images/markers/cjyl.gif',
                isGif: true,
                pulse: true,
                size: [20, 20]
            }
        ];

        // 创建矢量数据源
        const vectorSource = new ol.source.Vector();

        // 添加所有点到矢量图层（包括 GIF 和非 GIF 点）
        pointsData.forEach(point => {
            const feature = new ol.Feature({
                geometry: new ol.geom.Point(
                    ol.proj.fromLonLat(point.coordinates)
                ),
                name: point.name,
                type: point.type,
                icon: point.icon,
                isGif: point.isGif || false,
                pulse: point.pulse,
                pulseStartTime: point.pulseStartTime || Date.now()
            });
            vectorSource.addFeature(feature);
        });

        // 创建标注图层 - 用于所有点的文字标注
        const labelLayer = new ol.layer.Vector({
            source: vectorSource,
            style: function(feature) {
                let style = new ol.style.Style({
                    text: new ol.style.Text({
                        text: feature.get('name'),
                        font: '12px sans-serif',
                        offsetY: 25,
                        textAlign: 'center',
                        textBaseline: 'middle',
                        fill: new ol.style.Fill({
                            color: '#333'
                        }),
                        stroke: new ol.style.Stroke({
                            color: '#fff',
                            width: 3
                        })
                    })
                });

                // 只为非 GIF 点添加图标
                if (!feature.get('isGif')) {
                    style.setImage(new ol.style.Icon({
                        src: feature.get('icon'),
                        scale: 0.8,
                        anchor: [0.5, 0.5],
                        anchorXUnits: 'fraction',
                        anchorYUnits: 'fraction'
                    }));
                }

                return style;
            }
        });

        // 创建闪烁效果图层 - 用于所有需要闪烁的点
        const pulseLayer = new ol.layer.Vector({
            source: vectorSource,
            style: function(feature) {
                if (!feature.get('pulse')) return null;

                const startTime = feature.get('pulseStartTime');
                const currentTime = Date.now();
                const elapsedTime = currentTime - startTime;

                if (elapsedTime <= 3000) {
                    const phase = (currentTime % 1500) / 1500;
                    const radius = 15 + (35 * phase);
                    const opacity = 0.8 - phase;

                    return new ol.style.Style({
                        image: new ol.style.Circle({
                            radius: radius,
                            fill: new ol.style.Fill({
                                color: `rgba(255, 0, 0, ${opacity * 0.3})`
                            }),
                            stroke: new ol.style.Stroke({
                                color: `rgba(255, 0, 0, ${opacity})`,
                                width: 2
                            })
                        })
                    });
                } else {
                    feature.set('pulse', false);
                    return null;
                }
            }
        });

        /**
         * 创建地图对象
         * @see https://openlayers.org/en/latest/apidoc/module-ol_Map-Map.html
         */
        const map = new ol.Map({
            target: 'map',
            layers: [
                // 高德地图底图
                new ol.layer.Tile({
                    source: new ol.source.XYZ({
                        url: 'https://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
                        crossOrigin: 'anonymous'
                    })
                }),
                pulseLayer,  // 闪烁效果图层放在标注图层下面
                labelLayer,   // 标注图层
            ],
            view: new ol.View({
                center: ol.proj.fromLonLat([116.397428, 39.90923]), // 地图中心点
                zoom: 12  // 缩放级别
            })
        });

        // 修改 GIF Overlays 创建部分
        pointsData.filter(point => point.isGif).forEach(point => {
            // 创建 GIF 标记容器
            const gifElement = document.createElement('div');
            gifElement.className = 'gif-marker';
            gifElement.style.backgroundImage = `url(${point.icon})`;
            
            // 如果指定了大小，则设置具体尺寸
            if (point.size) {
                gifElement.style.width = `${point.size[0]}px`;
                gifElement.style.height = `${point.size[1]}px`;
            }

            // 创建 GIF Overlay
            const gifOverlay = new ol.Overlay({
                element: gifElement,
                position: ol.proj.fromLonLat(point.coordinates),
                positioning: 'center-center',
                offset: [0, 0]
            });

            // 添加到地图
            map.addOverlay(gifOverlay);
        });

        /**
         * 新增点位功能
         */
        let isAddingPoint = false;
        const addPointBtn = document.getElementById('addPointBtn');
        const addPointTip = document.getElementById('addPointTip');

        // 点击按钮切换状态
        addPointBtn.addEventListener('click', function () {
            isAddingPoint = !isAddingPoint;
            addPointBtn.classList.toggle('active');
            addPointTip.classList.toggle('show');
            map.getTarget().style.cursor = isAddingPoint ? 'crosshair' : '';
        });

        // 地图点击事件
        map.on('click', function (evt) {
            if (!isAddingPoint) return;

            // 获取点击位置的坐标并转换为经纬度
            const coords = ol.proj.transform(evt.coordinate, 'EPSG:3857', 'EPSG:4326');

            // 创建新的点位数据
            const newPoint = {
                type: 'new',
                name: `新增点位 ${vectorSource.getFeatures().length + 1}`,
                coordinates: coords,
                icon: '/images/markers/PP_CJ.png',
                pulse: true,
                pulseStartTime: Date.now()
            };

            // 创建新的要素
            const feature = new ol.Feature({
                geometry: new ol.geom.Point(evt.coordinate),
                name: newPoint.name,
                type: newPoint.type,
                icon: newPoint.icon,
                pulse: newPoint.pulse,
                pulseStartTime: newPoint.pulseStartTime
            });

            // 添加到数据源
            vectorSource.addFeature(feature);

            // 重新启动动画
            animate();

            // 关闭新增点模式
            isAddingPoint = false;
            addPointBtn.classList.remove('active');
            addPointTip.classList.remove('show');
            map.getTarget().style.cursor = '';
        });

        // 修改鼠标样式处理，考虑新增点模式
        map.on('pointermove', function (e) {
            if (isAddingPoint) {
                map.getViewport().style.cursor = 'crosshair';
                return;
            }
            const pixel = map.getEventPixel(e.originalEvent);
            const hit = map.hasFeatureAtPixel(pixel);
            map.getViewport().style.cursor = hit ? 'pointer' : '';
        });

        /**
         * 显示鼠标位置坐标
         * @see https://openlayers.org/en/latest/apidoc/module-ol_coordinate.html
         */
        map.on('pointermove', function (evt) {
            const coords = ol.proj.transform(evt.coordinate, 'EPSG:3857', 'EPSG:4326');
            document.getElementById('coordinates').innerHTML =
                `经度: ${coords[0].toFixed(6)}, 纬度: ${coords[1].toFixed(6)}`;
        });

        // 修改动画函数
        function animate() {
            const hasActivePulse = vectorSource.getFeatures().some(feature => 
                feature.get('pulse') && 
                (Date.now() - feature.get('pulseStartTime') <= 3000)
            );

            if (hasActivePulse) {
                pulseLayer.changed();  // 改回更新 pulseLayer
                map.render();
                requestAnimationFrame(animate);
            }
        }

        // 只启动一个动画循环
        animate();
    </script>
</body>

</html>